#/usr/bin/env python3

import paramiko
import argparse
import csv
import os
import sys
import logging

def arg_parse():
    parser = argparse.ArgumentParser()
    parser.add_argument('-c','--connfile',help='ssh connnection info file',required=True)
    parser.add_argument('-C','--cmdfile',help='ssh commands file',required=True)
    args = parser.parse_args()
    return args

def ssh_conn(*args):
    try:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(hostname=args[0],port=args[1],username=args[2],password=args[3])
        logger.info(args[0] + ' [-] ssh connected')
        return client
    except Exception as e:
        logger.error(args[0] + ' [-] ssh connect failed: ' + str(e))
        client.close()
        return None

def exec_cmd(host, sshclient, cmdfile):
    with open(cmdfile,'r') as cf:
        for cmd in cf:
            cmd = cmd.strip()
            if cmd:
                try:
                    stdin, stdout, stderr = client.exec_command(cmd, timeout=30)
                    ssh_out = stdout.read().decode()
                    ssh_err = stderr.read().decode()
                    logger.info(host + ' [-] execute command "' + cmd + '"')
                    if ssh_out:
                        logger.info(host + ' [-] command output:\n' + ssh_out)
                    if ssh_err:
                        logger.error(host + ' [-] command error messages:\n' + ssh_err)
                except Exception as e:
                    logger.error(host + ' [-] execute command "' + cmd + '" failed: ' + str(e))
                    sshclient.close()
                    return False
    sshclient.close()
    return True

def log(logfile):
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    fhlr = logging.FileHandler(logfile)
    shlr = logging.StreamHandler(sys.stdout)

    fhlr.setLevel(logging.INFO)
    shlr.setLevel(logging.INFO)

    formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
    fhlr.setFormatter(formatter)
    shlr.setFormatter(formatter)

    logger.addHandler(fhlr)
    logger.addHandler(shlr)
    return logger

if __name__ == '__main__':
    ## 获取日志文件名, 日志文件与程序文件保存在同一目录下
    logfile = os.path.basename(__file__).split('.')[0] + '.log'
    logger = log(logfile)
    ## 处理输入参数
    args = arg_parse()
    connfile = args.connfile
    cmdfile = args.cmdfile
    ## 检查文件是否存在
    if (not os.path.exists(connfile)) or (not os.path.exists(cmdfile)):
        logger.error('file ' + connfile + ' or ' + cmdfile + ' does not exist')
        sys.exit(1)
    with open(connfile,'r') as f1:
        conns = csv.reader(f1)
        for conn in conns:
            if conn:
                client = ssh_conn(*conn)
                if client:
                    exec_cmd(conn[0], client, cmdfile)
